// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_HEAP_HEAP_CONTROLLER_H_
#define V8_HEAP_HEAP_CONTROLLER_H_

#include <cstddef>
#include "src/allocation.h"
#include "src/heap/heap.h"
//#include "testing/gtest/include/gtest/gtest_prod.h"  // nogncheck

namespace v8 {
namespace internal {

    class V8_EXPORT_PRIVATE MemoryController {
    public:
        MemoryController(Heap* heap, double min_growing_factor,
            double max_growing_factor,
            double conservative_growing_factor,
            double target_mutator_utilization)
            : heap_(heap)
            , min_growing_factor_(min_growing_factor)
            , max_growing_factor_(max_growing_factor)
            , conservative_growing_factor_(conservative_growing_factor)
            , target_mutator_utilization_(target_mutator_utilization)
        {
        }
        virtual ~MemoryController() = default;

        // Computes the allocation limit to trigger the next garbage collection.
        size_t CalculateAllocationLimit(size_t curr_size, size_t max_size,
            double max_factor, double gc_speed,
            double mutator_speed,
            size_t new_space_capacity,
            Heap::HeapGrowingMode growing_mode);

        // Computes the growing step when the limit increases.
        size_t MinimumAllocationLimitGrowingStep(Heap::HeapGrowingMode growing_mode);

    protected:
        double GrowingFactor(double gc_speed, double mutator_speed,
            double max_factor);
        virtual const char* ControllerName() = 0;

        Heap* const heap_;
        const double min_growing_factor_;
        const double max_growing_factor_;
        const double conservative_growing_factor_;
        const double target_mutator_utilization_;

        //   FRIEND_TEST(HeapControllerTest, HeapGrowingFactor);
        //   FRIEND_TEST(HeapControllerTest, MaxHeapGrowingFactor);
        //   FRIEND_TEST(HeapControllerTest, MaxOldGenerationSize);
        //   FRIEND_TEST(HeapControllerTest, OldGenerationAllocationLimit);
    };

    class V8_EXPORT_PRIVATE HeapController : public MemoryController {
    public:
        // Sizes are in MB.
        static constexpr size_t kMinSize = 128 * Heap::kPointerMultiplier;
        static constexpr size_t kMaxSize = 1024 * Heap::kPointerMultiplier;

        explicit HeapController(Heap* heap)
            : MemoryController(heap, 1.1, 4.0, 1.3, 0.97)
        {
        }
        double MaxGrowingFactor(size_t curr_max_size);

    protected:
        const char* ControllerName() override { return "HeapController"; }
    };

} // namespace internal
} // namespace v8

#endif // V8_HEAP_HEAP_CONTROLLER_H_
